﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Comp_Geo
{
    public class Monster : GameObject
    {
        private List<Node> path;
        private int factor = 4000;
        private int pathEntriesCount;
        private int count = 0;
        private int timeSinceLastUpdate;
        private int millisecondsPerUpdate = 4000;

        #region Initilization

        public Monster(Texture2D textureImage, Vector2 startPosition)
            : base(textureImage, startPosition)
        {
        }

        #endregion

        #region Update

        public void Update(GameTime gameTime)
        {
            timeSinceLastUpdate += gameTime.ElapsedGameTime.Milliseconds;
            if (path != null)
            {
                if (timeSinceLastUpdate > millisecondsPerUpdate)
                {
                    if (count != path.Count)
                    {
                        this.CurrPosition = path[count].Position;
                        count++;
                        timeSinceLastUpdate = 0;
                    }
                }
            }
        }

        #endregion

        #region A*

        public void AStar(Vector2 startPosition, Vector2 endPosition, Graph graph)
        {
            List<Node> closedSet = new List<Node>();
            List<Node> openSet = new List<Node>();
            List<Node> cameFrom = new List<Node>();
            // Set first node in openSet
            foreach (Node node in graph.Nodes)
            {
                if (node.Position == startPosition)
                {
                    node.gScore = 0;
                    node.hScore = setHurestic(node.Position, endPosition);
                    node.fScore = node.gScore + node.hScore;
                    openSet.Add(node);
                }
            }

            //int gScore = 0;
            //int hScore = setHurestic(startPosition, endPosition);
            //int fScore = gScore + hScore;
            int tenativeGScore;
            bool tenativeIsBetter;

            while (openSet.Count > 0)
            {
                Node x = new Node();
                int lowestFScore = 10000000; // An arbitraraly high number
                int findOpenSetIndex=-1; // A negative number.  Need to do a try catch some day

                foreach (Node node in openSet)
                {
                    if (node.fScore < lowestFScore)
                    {
                        lowestFScore = node.fScore;
                        x = node;
                        findOpenSetIndex = openSet.IndexOf(node);
                    }
                }

                if (x.Position == endPosition)
                {
                    cameFrom.Add(x);
                    Console.WriteLine();
                    Console.WriteLine("A* Found end");
                    foreach (Node node in cameFrom)
                    {
                        Console.WriteLine("NodeX:{0} NodeY:{1}", node.Position.X, node.Position.Y);
                    }
                    path = cameFrom;
                    pathEntriesCount = cameFrom.Count;
                }

                closedSet.Add(openSet[findOpenSetIndex]);
                openSet.RemoveAt(findOpenSetIndex);

                foreach (Node y in x.AdjacentNodes)
                {
                    if (closedSet.Contains(y))
                        continue;

                    tenativeGScore = x.gScore + (int)Vector2.Distance(x.Position, y.Position);

                    if (!openSet.Contains(y))
                    {
                        openSet.Add(y);
                        tenativeIsBetter = true;
                        if (!cameFrom.Contains(x))
                            cameFrom.Add(x);
                    }
                    else if (tenativeGScore < y.gScore)
                    {
                        tenativeIsBetter = true;
                    }
                    else
                        tenativeIsBetter = false;

                    if (tenativeIsBetter == true)
                    {
                        
                        y.gScore = tenativeGScore;
                        y.hScore = setHurestic(y.Position, endPosition);
                        y.fScore = y.gScore + y.hScore;
                    }
                }
            }
        }

        private int setHurestic(Vector2 startPosition, Vector2 endPosition)
        {
            float hScore = Vector2.Distance(startPosition, endPosition);
            hScore *= 1.5f;
            int hScoreI = (int)hScore;
            return hScoreI;
        }

        #endregion
    }
}
